package com.ayz.gateway.center.infrastructure.remoting.defaults;

import cn.hutool.core.thread.ThreadFactoryBuilder;

import com.ayz.gateway.center.domain.repository.IApiRepository;
import com.ayz.gateway.center.domain.repository.IGatewayServiceRepository;
import com.ayz.gateway.center.domain.service.remoting.RegistryApplicationServiceImpl;
import com.ayz.gateway.center.domain.service.remoting.RegistryGatewayServiceImpl;
import com.ayz.gateway.center.domain.service.remoting.SubscribeGatewayGroupServiceImpl;
import com.ayz.gateway.center.infrastructure.remoting.GatewayCenterService;
import com.ayz.gateway.center.infrastructure.remoting.config.GatewayCenterConfig;
import com.ayz.gateway.server.grpc.GrpcRemotingServer;
import com.ayz.gateway.server.grpc.GrpcServerConfig;
import com.ayz.gateway.server.service.ServerCheckServiceImpl;
import lombok.Data;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName DefaultGatewayCenterService
 * @Description TODO: 默认的网关注册中心服务端
 * @Author 快乐的星球
 * @Date 2023/5/23 21:18
 * @Version 1.0
 **/
@Data
public class DefaultGatewayCenterService implements GatewayCenterService {
    /**
     * 网关注册中心的配置参数
     */
    private GatewayCenterConfig gatewayCenterConfig;
    /**
     * GRPC远程通信的服务端组件
     */
    private GrpcRemotingServer remotingServer;
    /**
     * 执行定时任务的线程池
     */
    private final ScheduledExecutorService scheduledExecutorService= Executors.newSingleThreadScheduledExecutor(
            new ThreadFactoryBuilder().setDaemon(true).setNamePrefix("DefaultGatewayCenterScheduledThread_").build());
    /**
     * 网关注册中心的API内存缓存
     */
    private IApiRepository apiRepository;
    /**
     * 网关注册中心网关服务存储
     */
    private IGatewayServiceRepository gatewayServiceRepository;
    public DefaultGatewayCenterService(GatewayCenterConfig gatewayCenterConfig, GrpcRemotingServer remotingServer,IApiRepository apiRepository,
                                       IGatewayServiceRepository gatewayServiceRepository) {
        this.gatewayCenterConfig = gatewayCenterConfig;
        this.remotingServer = remotingServer;
        this.apiRepository=apiRepository;
        this.gatewayServiceRepository=gatewayServiceRepository;
    }

    public DefaultGatewayCenterService(GatewayCenterConfig gatewayCenterConfig, GrpcServerConfig grpcServerConfig, IApiRepository apiRepository,
                                       IGatewayServiceRepository gatewayServiceRepository){
        this.gatewayCenterConfig=gatewayCenterConfig;
        this.remotingServer=new GrpcRemotingServer(grpcServerConfig);
        this.apiRepository=apiRepository;
        this.gatewayServiceRepository=gatewayServiceRepository;
    }
    @Override
    public void start() {
        //1: 添加服务
        addServices();
        //2:启动远程通信服务端
        try {
            this.remotingServer.start();
        } catch (Exception e) {
            throw new RuntimeException("服务端启动失败!");
        }
        //3: 启动定时任务
        //3.1 网关注册中心定时扫描不活跃的应用程序，剔除其注册的API信息
        scheduledExecutorService.scheduleAtFixedRate(()->{
            getApiRepository().scanNotActiveApplication(getGatewayCenterConfig().getApplicationChannelExpiredTime());
        },getGatewayCenterConfig().getServerHealthDetectionTaskTime(), getGatewayCenterConfig().getServerHealthDetectionTaskTime(), TimeUnit.MILLISECONDS);
        //3.2 网关注册中心定时扫描剔除不活跃的网关服务
        scheduledExecutorService.scheduleAtFixedRate(()->{
            getGatewayServiceRepository().scanNotActiveGatewayService(gatewayCenterConfig.getGatewayServiceChannelExpiredTime());
        },getGatewayCenterConfig().getServerHealthDetectionTaskTime(), gatewayCenterConfig.getServerHealthDetectionTaskTime(), TimeUnit.MILLISECONDS);
    }
    /**
     *  向GRPC服务端注册一系列服务
     */
    private void addServices(){
        //1:接受客户端SDK的API注册
        this.remotingServer.addService(new RegistryApplicationServiceImpl(getApiRepository()));
        //2: 测试服务端通畅的服务
        this.remotingServer.addService(new ServerCheckServiceImpl());
        //3: 提供网关服务注册服务
        this.remotingServer.addService(new RegistryGatewayServiceImpl(getGatewayServiceRepository(),getApiRepository()));
        //4: 网关服务订阅指定业务组
        this.remotingServer.addService(new SubscribeGatewayGroupServiceImpl(getApiRepository(),getGatewayServiceRepository()));
    }
    @Override
    public void close() {
        //1:关闭远程通信服务端
        remotingServer.shutdown();
        //2:关闭线程池
        scheduledExecutorService.shutdownNow();
    }
}
